/**
 *
 * M.plugins.imglazy.install(options)
 *  - offset (Type: Number|String Default: 0)
 *    The offset option allows you to specify how far below, above, to the left, and to the right of the viewport you want imglazy to begin loading your images. If you specify 0, imglazy will load your image as soon as it is visible in the viewport, if you want to load 1000px below or above the viewport, use 1000.
 *  - offsetVertical (Type: Number|String Default: offset's value)
 *    The offsetVertical option allows you to specify how far above and below the viewport you want imglazy to begin loading your images.
 *  - offsetHorizontal (Type: Number|String Default: offset's value)
 *    The offsetHorizontal option allows you to specify how far to the left and right of the viewport you want imglazy to begin loading your images.
 *  - offsetTop (Type: Number|String Default: offsetVertical's value)
 *    The offsetTop option allows you to specify how far above the viewport you want imglazy to begin loading your images.
 *  - offsetBottom (Type: Number|String Default: offsetVertical's value)
 *    The offsetBottom option allows you to specify how far below the viewport you want imglazy to begin loading your images.
 *  - offsetLeft (Type: Number|String Default: offsetVertical's value)
 *    The offsetLeft option allows you to specify how far to left of the viewport you want imglazy to begin loading your images.
 *  - offsetRight (Type: Number|String Default: offsetVertical's value)
 *    The offsetRight option allows you to specify how far to the right of the viewport you want imglazy to begin loading your images.
 *  - throttle (Type: Number|String Default: 250)
 *    The throttle is managed by an internal function that prevents performance issues from continuous firing of window.onscroll events. Using a throttle will set a small timeout when the user scrolls and will keep throttling until the user stops. The default is 250 milliseconds.
 *  - debounce (Type: Boolean Default: true)
 *    By default the throttling function is actually a debounce function so that the checking function is only triggered after a user stops scrolling. To use traditional throttling where it will only check the images every throttle milliseconds, set debounce to false.
 *  - unload (Type: Boolean Default: false)
 *    This option will tell imglazy to unload loaded images once they have scrolled beyond the viewport (including the offset area).
 *  - callback (Type: Function)
 *    The callback will be passed the element that has been updated and what the update operation was (ie load or unload). This can be useful if you want to add a class like loaded to the element. Or do some logging.
 *
 * M.plugins.imglazy.render()
 *  imglazy's callback render() can be used to make imglazy poll your images when you're not scrolling, for instance if you've got a filter layout that swaps images but does not scroll, you need to call the internal functions without scrolling.
 *
 *
 * @source https://github.com/toddmotto/echo
 */
M.define('m/plugin/imglazy', function(require, exports, module) {

  var imglazy = {};

  var offset, poll, delay, useDebounce, unload;

  var inView = function(element, view) {
    var box = element.getBoundingClientRect();
    return (box.right >= view.l && box.bottom >= view.t && box.left <= view.r && box.top <= view.b);
  };

  var debounceOrThrottle = function() {
    if (!useDebounce && !!poll) {
      return;
    }
    clearTimeout(poll);
    poll = setTimeout(function() {
      imglazy.render();
      poll = null;
    }, delay);
  };

  imglazy.install = function(opts) {
    opts = opts || {};
    var offsetAll = opts.offset || 0;
    var offsetVertical = opts.offsetVertical || offsetAll;
    var offsetHorizontal = opts.offsetHorizontal || offsetAll;
    var optionToInt = function(opt, fallback) {
      return parseInt(opt || fallback, 10);
    };
    offset = {
      t: optionToInt(opts.offsetTop, offsetVertical),
      b: optionToInt(opts.offsetBottom, offsetVertical),
      l: optionToInt(opts.offsetLeft, offsetHorizontal),
      r: optionToInt(opts.offsetRight, offsetHorizontal)
    };
    delay = optionToInt(opts.throttle, 250);
    useDebounce = opts.debounce !== false;
    unload = !!opts.unload;
    callback = opts.callback || M.noop;
    imglazy.render();
    if (document.addEventListener) {
      window.addEventListener('scroll', debounceOrThrottle, false);
      window.addEventListener('load', debounceOrThrottle, false);
    } else {
      window.attachEvent('onscroll', debounceOrThrottle);
      window.attachEvent('onload', debounceOrThrottle);
    }
  };

  imglazy.render = function() {
    var nodes = document.querySelectorAll('img[data-src], [data-src-background]');
    var length = nodes.length;
    var src, elem;
    var view = {
      l: 0 - offset.l,
      t: 0 - offset.t,
      b: (window.innerHeight || document.documentElement.clientHeight) + offset.b,
      r: (window.innerWidth || document.documentElement.clientWidth) + offset.r
    };
    for (var i = 0; i < length; i++) {
      elem = nodes[i];
      if (inView(elem, view)) {

        if (unload) {
          elem.setAttribute('data-src-placeholder', elem.src);
        }

        if (elem.getAttribute('data-src-background') !== null) {
          elem.style.backgroundImage = "url(" + elem.getAttribute('data-src-background') + ")";
        } else {
          elem.src = elem.getAttribute('data-src');
        }

        if (!unload) {
          elem.removeAttribute('data-src');
        }

        callback(elem, 'load');
      } else if (unload && !!(src = elem.getAttribute('data-src-placeholder'))) {

        if (elem.getAttribute('data-src-background') !== null) {
          elem.style.backgroundImage = 'url(' + src + ')';
        } else {
          elem.src = src;
        }

        elem.removeAttribute('data-src-placeholder');
        callback(elem, 'unload');
      }
    }
    if (!length) {
      imglazy.detach();
    }
  };

  imglazy.detach = function() {
    if (document.removeEventListener) {
      window.removeEventListener('scroll', debounceOrThrottle);
    } else {
      window.detachEvent('onscroll', debounceOrThrottle);
    }
    clearTimeout(poll);
  };

  module.exports = imglazy;

});

M.plugins.imglazy = M.require('m/plugin/imglazy');